package me.landery.modules.sinco.service.impl;

import lombok.RequiredArgsConstructor;
import me.landery.modules.sinco.domain.News;
import me.landery.modules.sinco.repository.NewsRepository;
import me.landery.modules.sinco.service.NewsService;
import me.landery.modules.sinco.service.dto.NewsDto;
import me.landery.modules.sinco.service.dto.NewsQueryCriteria;
import me.landery.modules.sinco.service.mapstruct.NewsMapper;
import me.landery.utils.FileUtil;
import me.landery.utils.PageUtil;
import me.landery.utils.QueryHelp;
import me.landery.utils.ValidationUtil;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @Author cc.w
 * @Date 2022/6/15 15:32
 * @Version 1.0
 */
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "news")
public class NewsServiceImpl implements NewsService {

    private final NewsRepository newsRepository;
    private final NewsMapper newsMapper;

    @Override
    public Map<String, Object> queryAll(NewsQueryCriteria criteria, Pageable pageable) {
        Page<News> page = newsRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(newsMapper::toDto).getContent(),page.getTotalElements());
    }

    @Override
    public void create(News resources) {
        newsRepository.save(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(News resources) {
        News news = newsRepository.findById(resources.getId()).orElseGet(News::new);
        ValidationUtil.isNull( news.getId(),"News","id",resources.getId());
        news.copy(resources);
        newsRepository.save(news);
    }

    @Override
    @Cacheable(key = "'id:' + #p0")
    @Transactional(rollbackFor = Exception.class)
    public NewsDto findById(Long id) {
        News news = newsRepository.findById(id).orElseGet(News::new);
        ValidationUtil.isNull(news.getId(), "News", "id", id);
        return newsMapper.toDto(news);
    }

    @Override
    public List<NewsDto> queryAll(NewsQueryCriteria criteria) {
        return newsMapper.toDto(newsRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    public void deleteAll(Long[] ids) {
        for (Long newsId : ids) {
            newsRepository.deleteById(newsId);
        }
    }

    @Override
    public void download(List<NewsDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (NewsDto news : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("新闻标题", news.getTitle());
            map.put("新闻内容", news.getContent());
            map.put("发布时间", news.getTime());
            map.put("创建日期", news.getCreateTime());
            map.put("更新时间", news.getUpdateTime());
            map.put("创建者", news.getCreateBy());
            map.put("更新者", news.getUpdateBy());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Set<Long> ids) {
        for (Long id : ids) {
            // 清理缓存
            NewsDto news = findById(id);
//            delCaches(user.getId(), user.getUsername());
        }
        newsRepository.deleteAllByIdIn(ids);
    }
}
